package edu.qichen.onlineBlog.user.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.qichen.onlineBlog.framework.DataResult;
import edu.qichen.onlineBlog.framework.exception.BusinessException;
import edu.qichen.onlineBlog.framework.exception.ErrorCodeEnum;
import edu.qichen.onlineBlog.framework.utils.RedisUtils;
import edu.qichen.onlineBlog.framework.utils.TokenUtils;
import edu.qichen.onlineBlog.framework.validata.ValidatorUtil;
import edu.qichen.onlineBlog.user.dto.*;
import edu.qichen.onlineBlog.user.pojo.User;
import edu.qichen.onlineBlog.user.mapper.UserMapper;
import edu.qichen.onlineBlog.user.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 功能:
 * 作者:程序员欧阳子韩
 * 日期:2024/3/27 17:09
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserMapper userMapper;

    private final RedisUtils redisUtils;

    @Override
    public Boolean findByEmail(String email) {
        ValidatorUtil.validateEntity(email);

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, email);

        List<User> users = baseMapper.selectList(wrapper);
        return users != null && !users.isEmpty();
    }

    @Override
    public List<User> queryUserInfo() {
        QueryWrapper<User> wrapper = new QueryWrapper<>();

        return baseMapper.selectList(wrapper);
    }

    @Override
    public UserLoginRes login(UserLoginReq userLoginReq, HttpServletRequest request) {
        ValidatorUtil.validateEntity(userLoginReq);

        LambdaQueryWrapper<User> queryWrapper = Wrappers.lambdaQuery();
        if (StrUtil.isNotBlank(userLoginReq.getUsername())) {
            queryWrapper.eq(User::getUsername, userLoginReq.getUsername());
        }
        User user = this.getOne(queryWrapper);

        if (user == null) {
            throw BusinessException.build(ErrorCodeEnum.USERNAME_OR_PASSWORD_NULL_ERROR);
        }
        if (!StrUtil.equals(SecureUtil.md5(userLoginReq.getPassword()), user.getPassword())) {
            throw BusinessException.build(ErrorCodeEnum.USERNAME_OR_PASSWORD_EQ_ERROR);
        }

        UserLoginRes userLoginRes = new UserLoginRes();
        userLoginRes.setId(user.getId());
        userLoginRes.setUsername(user.getUsername());
        userLoginRes.setPassword(user.getPassword());
        userLoginRes.setRole(user.getRole());
        userLoginRes.setNickname(user.getNickname());
        userLoginRes.setEmail(user.getEmail());
        userLoginRes.setUserPic(user.getUserPic());

        // 生成token
        String token = TokenUtils.getToken(user.getId().toString(), user.getPassword());

        redisUtils.set(user.getId().toString(), token, 2 * 60 * 60);

        userLoginRes.setToken(token);

        HttpSession session = request.getSession();
        session.setAttribute("username", user.getUsername());


        return userLoginRes;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserLoginRes register(UserRegisterReq registerReq, HttpServletRequest request) {
        ValidatorUtil.validateEntity(registerReq);

        // 检查邮件地址是否包含@符号
        int atIndex = registerReq.getEmail().indexOf('@');

        if (atIndex == -1) {
            throw BusinessException.build(ErrorCodeEnum.EMAIL_FORMAT_ERROR);
        }

        // 默认密码为123456
        String password = "123456";


        // 存储用户名到数据库
        User user = new User();
        user.setUsername(registerReq.getEmail());
        user.setPassword(SecureUtil.md5(password));
        user.setEmail(registerReq.getEmail());

        baseMapper.insert(user);

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(registerReq.getEmail())) {
            wrapper.eq(User::getEmail, registerReq.getEmail());
        }

        User users = this.getOne(wrapper);

        UserLoginRes registerRes = new UserLoginRes();

        registerRes.setId(users.getId());
        registerRes.setUsername(users.getUsername());
        registerRes.setPassword(users.getPassword());
        registerRes.setRole(users.getRole());
        registerRes.setNickname(users.getNickname());
        registerRes.setEmail(users.getEmail());
        registerRes.setUserPic(users.getUserPic());

        String token = TokenUtils.getToken(users.getId().toString(), users.getPassword());

        redisUtils.set(user.getId().toString(), token, 2 * 60 * 60 * 1000);

        registerRes.setToken(token);

        HttpSession session = request.getSession();
        session.setAttribute("username", users.getUsername());


        return registerRes;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public User updateUser(UserUpdateReq userUpdateReq, HttpServletRequest request) {
        ValidatorUtil.validateEntity(userUpdateReq);

        // 检查邮件地址是否包含@符号
        int atIndex = userUpdateReq.getEmail().indexOf('@');
        if (atIndex == -1) {
            throw BusinessException.build(ErrorCodeEnum.EMAIL_FORMAT_ERROR);
        }

        User user = new User();
        user.setId(userUpdateReq.getId());
        user.setUsername(userUpdateReq.getUsername());
        user.setNickname(userUpdateReq.getNickname());
        user.setEmail(userUpdateReq.getEmail());
        user.setRole(user.getRole());
        user.setUserPic(userUpdateReq.getUserPic());


        baseMapper.updateById(user);

        HttpSession session = request.getSession();
        session.setAttribute("username", Objects.requireNonNull(TokenUtils.getCurrentUser()).getUsername());

        // 获取更新后的用户
        User updatedUser = baseMapper.selectById(userUpdateReq.getId());
        if (updatedUser == null) {
            throw BusinessException.build(ErrorCodeEnum.SERVER_UPDATE_QUERY_ERROR);
        }
        return updatedUser;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public User addUser(UserAddReq userAddReq, HttpServletRequest request) {
        ValidatorUtil.validateEntity(userAddReq);

        // 默认密码为123456
        String password = "123456";


        User user = new User();
        user.setUsername(userAddReq.getUsername());
        user.setPassword(SecureUtil.md5(password));
        user.setNickname(userAddReq.getNickname());
        user.setEmail(userAddReq.getEmail());
        user.setRole(userAddReq.getRole());

        baseMapper.insert(user);

        HttpSession session = request.getSession();
        session.setAttribute("username", Objects.requireNonNull(TokenUtils.getCurrentUser()).getUsername());
        return user;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updatePwd(UpdatePwdReq updatePwdReq, HttpServletRequest request) {
        ValidatorUtil.validateEntity(updatePwdReq);
        User currentUser = TokenUtils.getCurrentUser();

        assert currentUser != null;
        Long id = currentUser.getId();
        String password = currentUser.getPassword();

        String newPassword = updatePwdReq.getPassword();
        if (Objects.equals(password, newPassword)) {
            throw BusinessException.build(ErrorCodeEnum.OLD_NEW_EQUALS);
        }
        password = SecureUtil.md5(newPassword);

        User user = new User();

        user.setId(id);
        user.setPassword(password);

        baseMapper.updateById(user);

        HttpSession session = request.getSession();
        session.setAttribute("username", Objects.requireNonNull(TokenUtils.getCurrentUser()).getUsername());
        return true;
    }

    @Override
    public PageUserRes userPage(PageUserReq pageUserReq) {
        Long pageNum = pageUserReq.getPageNum();
        Long pageSize = pageUserReq.getPageSize();
        Page<User> page = new Page<>(pageNum, pageSize);

        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(User::getId);
        queryWrapper.like(StrUtil.isNotBlank(pageUserReq.getUsername()), User::getUsername, "%" + pageUserReq.getUsername() + "%");
        queryWrapper.like(StrUtil.isNotBlank(pageUserReq.getNickname()), User::getNickname, "%" + pageUserReq.getNickname() + "%");

        Page<User> userPage = baseMapper.selectPage(page, queryWrapper);

        PageUserRes pageUserRes = new PageUserRes();

        pageUserRes.setUser(userPage.getRecords());
        pageUserRes.setPageNum(userPage.getCurrent());
        pageUserRes.setPages(userPage.getPages());
        pageUserRes.setPageSize(userPage.getSize());
        pageUserRes.setTotal(userPage.getTotal());

        return pageUserRes;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean deleteById(Long id, HttpServletRequest request) {
        HttpSession session = request.getSession();
        session.setAttribute("username", Objects.requireNonNull(TokenUtils.getCurrentUser()).getUsername());
        baseMapper.deleteById(id);
        return true;
    }

    @Override
    public User validateTokenAndGetUser(String userId, String token) {
        // 从缓存中获取用户的最新token
        String storedToken = (String) redisUtils.get(userId);
        // 检查提供的token是否与存储的token匹配
        if (StrUtil.equals(storedToken, token)) {
            // 如果匹配，从数据库中获取用户信息并返回
            return baseMapper.selectById(Integer.valueOf(userId));
        } else {
            // 如果不匹配，抛出异常
            throw BusinessException.build(ErrorCodeEnum.AUTH_ERROR);
        }
    }

    @Override
//    @DataScope(deptAlias = "d",userAlias = "u")
    public List<UserExportDTO> selectUserList(UserExportDTO user, HttpServletRequest request) {
        ValidatorUtil.validateEntity(user);
        HttpSession session = request.getSession();
        session.setAttribute("username", Objects.requireNonNull(TokenUtils.getCurrentUser()).getUsername());
        return userMapper.selectUserList(user);
    }

    @Override
    public List<UserExportDTO> selectUserExportList(String username, String nickname, List<Integer> idsList) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(username), User::getUsername, "%" + username + "%");
        queryWrapper.like(StrUtil.isNotBlank(nickname), User::getNickname, "%" + nickname + "%");
        if (CollectionUtil.isNotEmpty(idsList)) {
            queryWrapper.in(User::getId, idsList);
        }

        List<User> users = baseMapper.selectList(queryWrapper);

        List<UserExportDTO> userExportDTOList = new ArrayList<>();

        users.forEach(data -> {
            UserExportDTO userExportDTO = new UserExportDTO();
            userExportDTO.setId(data.getId());
            userExportDTO.setUsername(data.getUsername());
            userExportDTO.setRole(data.getRole());
            userExportDTO.setNickname(data.getNickname());
            userExportDTO.setEmail(data.getEmail());
            userExportDTO.setCreateTime(data.getCreateTime());
            userExportDTO.setUpdateTime(data.getUpdateTime());
            userExportDTOList.add(userExportDTO);
        });

        return userExportDTOList;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void insert(List<UserExportDTO> userExportDTOS) {
        ValidatorUtil.validateEntity(userExportDTOS);

        userExportDTOS.forEach(data -> {
            User user = new User();
            if (this.findByUsername(data.getUsername())) {
                throw BusinessException.build(ErrorCodeEnum.USERNAME_REPEAT_ERROR ,data.getUsername());
            }
            user.setUsername(data.getUsername());
            user.setRole(data.getRole());
            user.setNickname(data.getNickname());
            if (this.findByEmail(data.getEmail())) {
                throw BusinessException.build(ErrorCodeEnum.EMAIL_REPEAT_ERROR ,data.getEmail());
            }
            user.setEmail(data.getEmail());
            baseMapper.insert(user);
        });
    }

    @Override
    public boolean findByUsername(String username) {
        ValidatorUtil.validateEntity(username);

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, username);

        List<User> users = baseMapper.selectList(wrapper);
        return users != null && !users.isEmpty();
    }

}
